/* ***************************************************************************
 **    display.c
 **
 **  Project      : ClockMatrix_v0
 **  Target       : PIC18F14K50
 **  Description  : Project used to develop clock firmware.  Tested methods and
 **                 determined functionality (needed, wanted, and the possible)
 **
 **  Compiler     : HI-TECH C  Version 9.80
 **  IDE          : MPLABX v1.80
 **  Created      : 5/8/2013
 **  Branched     : 6/27/2013 -- started v2
 **
 **  R Hanlen <implod@gmail.com>
 ** ***************************************************************************/

//  Global Includes
#include <htc.h>
#include <stdint.h>
#include <string.h>

//  Local Includes
#include "global.h"
#include "delay.h"
#include "shift_register.h"
#include "display.h"

void DisplayInit(void){

    ShiftRegInit();
    ClearDisplay();
    display.scrollDelay = 40;
}

void ClearDisplay(void){
    int i;

    // Initialise the display state
    for (i = 0; i < 8; i++) {
        display.row[i].byte_1 = 0x00;
        display.row[i].byte_2 = 0x00;
    }

    // Set the row to be displayed
    display.presentRow = 0;
}

void FlipDisplay(void){
    int i, j;

    // Initialise the display state
    for (i = 0; i < 8; i++) {
        for (j = 0; j < 8; j++) {
            display.row[i].byte_1 ^= (1 << j);
            display.row[i].byte_2 ^= (1 << j);
        }
    }

    // Set the row to be displayed
    display.presentRow = 0;
}

void DisplayPlot(unsigned char x, unsigned char y, unsigned char state){
    // Check for out of bounds
    if (x > 15 || y > 7) {
        return;
    }

    // Read the byte at the current location
    if (x < 8) {
        if (state == ON) display.row[y].byte_1 |= 0b10000000 >> x;
        else display.row[y].byte_1 &= 0b01111111 >> x;
    } else {
        if (state == ON) display.row[y].byte_2 |= 0b10000000 >> (x - 8);
        else display.row[y].byte_2 &= 0b01111111 >> (x - 8);
    }
}

//void DisplayLine(int x0, int y0, int x1, int y1, unsigned char state){
//    int dy = y1 - y0;
//    int dx = x1 - x0;
//    int stepx, stepy;
//
//    if (dy < 0) {
//        dy = -dy;
//        stepy = -1;
//    } else stepy = 1;
//
//    if (dx < 0) {
//        dx = -dx;
//        stepx = -1;
//    } else stepx = 1;
//
//    dy <<= 1; // dy is now 2*dy
//    dx <<= 1; // dx is now 2*dx
//
//    DisplayPlot(x0, y0, state);
//
//    if (dx > dy) {
//        int fraction = dy - (dx >> 1); // same as 2*dy - dx
//        while(x0 != x1) {
//            if (fraction >= 0) {
//                y0 += stepy;
//                fraction -= dx; // same as fraction -= 2*dx
//            }
//
//            x0 += stepx;
//            fraction += dy; // same as fraction -= 2*dy
//            DisplayPlot(x0, y0, state);
//        }
//    } else {
//        int fraction = dx - (dy >> 1);
//        while(y0 != y1) {
//            if (fraction >= 0) {
//                x0 += stepx;
//                fraction -= dy;
//            }
//
//            y0 += stepy;
//            fraction += dx;
//            DisplayPlot(x0, y0, state);
//        }
//    }
//}
//
//void DisplayRectangle(int x0, int y0, int x1, int y1, unsigned char state){
//    DisplayLine(x0, y0, x0, y1, state);
//    DisplayLine(x0, y1, x1, y1, state);
//    DisplayLine(x1, y0, x1, y1, state);
//    DisplayLine(x0, y0, x1, y0, state);
//}
//
//void DisplayFilledRectangle(int x0, int y0, int x1, int y1, unsigned char state){
//    unsigned char x, y;
//
//    // Plot the rectangle.  No need to use the line routine here since
//    // direct plotting is quicker for straight lines.
//    for (y = y0; y <= y1; y++)
//        for (x = x0; x <= x1; x++)
//            DisplayPlot(x, y, state);
//}

void DisplayCircle(int xCentre, int yCentre, int radius, unsigned int state){
    int x = 0, y = radius;
    int d = 3 - (2 * radius);

    while(x <= y) {
        DisplayPlot(xCentre + x, yCentre + y, state);
        DisplayPlot(xCentre + y, yCentre + x, state);
        DisplayPlot(xCentre - x, yCentre + y, state);
        DisplayPlot(xCentre + y, yCentre - x, state);
        DisplayPlot(xCentre - x, yCentre - y, state);
        DisplayPlot(xCentre - y, yCentre - x, state);
        DisplayPlot(xCentre + x, yCentre - y, state);
        DisplayPlot(xCentre - y, yCentre + x, state);

        if (d < 0) d += (4 * x) + 6;
        else {
            d += (4 * (x - y)) + 10;
            y -= 1;
        }

        x++;
    }
}

//void DisplayChar(uint8_t digit){
//    int tempColumn = 0;
//    unsigned char x = 0;
//    unsigned char y = 0;
//
//
//    ClearDisplay();
//    while(tempColumn < 5) {
//        if ((Font8x5[digit - 32][tempColumn] & 0b00000001) != 0) DisplayPlot(x, y, ON);
//        y++;
//        if ((Font8x5[digit - 32][tempColumn] & 0b00000010) != 0) DisplayPlot(x, y, ON);
//        y++;
//        if ((Font8x5[digit - 32][tempColumn] & 0b00000100) != 0) DisplayPlot(x, y, ON);
//        y++;
//        if ((Font8x5[digit - 32][tempColumn] & 0b00001000) != 0) DisplayPlot(x, y, ON);
//        y++;
//        if ((Font8x5[digit - 32][tempColumn] & 0b00010000) != 0) DisplayPlot(x, y, ON);
//        y++;
//        if ((Font8x5[digit - 32][tempColumn] & 0b00100000) != 0) DisplayPlot(x, y, ON);
//        y++;
//        if ((Font8x5[digit - 32][tempColumn] & 0b01000000) != 0) DisplayPlot(x, y, ON);
//        y++;
//        if ((Font8x5[digit - 32][tempColumn] & 0b10000000) != 0) DisplayPlot(x, y, ON);
//
//        y -= 7;
//        x++;
//        tempColumn++;
//
//    }
//}

void DisplayString(void){
    int tempColumn = 0;
    int tempCharacter = 0;
    unsigned char x = 0;
    unsigned char y = 0;
    unsigned char currentColumn;

    ClearDisplay();

    // Plot a display full of text
    for (currentColumn = 0; currentColumn < 16; currentColumn++) {
        // Only plot if character is in range
        if (tempCharacter < strlen(displayString)) {
            // Display a single column of 8 bits
            if ((Font8x5[displayString[tempCharacter] - 32][tempColumn] & 0b00000001) != 0) DisplayPlot(x, y, ON);
            y++;
            if ((Font8x5[displayString[tempCharacter] - 32][tempColumn] & 0b00000010) != 0) DisplayPlot(x, y, ON);
            y++;
            if ((Font8x5[displayString[tempCharacter] - 32][tempColumn] & 0b00000100) != 0) DisplayPlot(x, y, ON);
            y++;
            if ((Font8x5[displayString[tempCharacter] - 32][tempColumn] & 0b00001000) != 0) DisplayPlot(x, y, ON);
            y++;
            if ((Font8x5[displayString[tempCharacter] - 32][tempColumn] & 0b00010000) != 0) DisplayPlot(x, y, ON);
            y++;
            if ((Font8x5[displayString[tempCharacter] - 32][tempColumn] & 0b00100000) != 0) DisplayPlot(x, y, ON);
            y++;
            if ((Font8x5[displayString[tempCharacter] - 32][tempColumn] & 0b01000000) != 0) DisplayPlot(x, y, ON);
            y++;
            if ((Font8x5[displayString[tempCharacter] - 32][tempColumn] & 0b10000000) != 0) DisplayPlot(x, y, ON);

            // Reset y and add one to x ready for the next column
            y -= 7;
            x++;
        }

        // Increment the column to be displayed
        tempColumn++;

        // End of character?
        if (tempColumn == 5) {
            // Next character
            tempColumn = 0;
            tempCharacter++;
        }
    }
}

void DisplayScrollText(void){

    int character = 0;
    int column = 0;
    int currentColumn;
    int tempColumn;
    int tempCharacter;
    unsigned char x = 0;
    unsigned char y = 0;
    scrollFlag = 0;

    do {

        if (scrollFlag == 1) {
            scrollFlag = 0;
            return;
        }
        // Store the temp variables
        tempColumn = column;
        tempCharacter = character;

        // Reset x and y
        x = 0;
        y = 0;

        ClearDisplay();

        // Plot a display full of text
        for (currentColumn = 0; currentColumn < 16; currentColumn++) {
            // Only plot if character is in range
            if (tempCharacter < strlen(displayString)) {
                // Display a single column of 8 bits
                if ((Font8x5[displayString[tempCharacter] - 32][tempColumn] & 0b00000001) != 0) DisplayPlot(x, y, ON);
                y++;
                if ((Font8x5[displayString[tempCharacter] - 32][tempColumn] & 0b00000010) != 0) DisplayPlot(x, y, ON);
                y++;
                if ((Font8x5[displayString[tempCharacter] - 32][tempColumn] & 0b00000100) != 0) DisplayPlot(x, y, ON);
                y++;
                if ((Font8x5[displayString[tempCharacter] - 32][tempColumn] & 0b00001000) != 0) DisplayPlot(x, y, ON);
                y++;
                if ((Font8x5[displayString[tempCharacter] - 32][tempColumn] & 0b00010000) != 0) DisplayPlot(x, y, ON);
                y++;
                if ((Font8x5[displayString[tempCharacter] - 32][tempColumn] & 0b00100000) != 0) DisplayPlot(x, y, ON);
                y++;
                if ((Font8x5[displayString[tempCharacter] - 32][tempColumn] & 0b01000000) != 0) DisplayPlot(x, y, ON);
                y++;
                if ((Font8x5[displayString[tempCharacter] - 32][tempColumn] & 0b10000000) != 0) DisplayPlot(x, y, ON);

                // Reset y and add one to x ready for the next column
                y -= 7;
                x++;
            }

            // Increment the column to be displayed
            tempColumn++;

            // End of character?
            if (tempColumn == 5) {
                // Next character
                tempColumn = 0;
                tempCharacter++;
                x++;
            }
        }

        // Get ready for the next display full
        column++;
        if (column == 5) {
            column = 0;
            character++;
        }

        DelayMs(display.scrollDelay);
    } while(character < strlen(displayString));
}

//void DisplayScrollSmallText(void){
//
//    int character = 0;
//    int column = 0;
//    int currentColumn;
//    int tempColumn;
//    int tempCharacter;
//    unsigned char x = 0;
//    unsigned char y = 0;
//    scrollFlag = 0;
//
//    do {
//        if (scrollFlag == 1) {
//            scrollFlag = 0;
//            return;
//        }
//        // Store the temp variables
//        tempColumn = column;
//        tempCharacter = character;
//
//        // Reset x and y
//        x = 0;
//        y = 0;
//
//        ClearDisplay();
//
//        // Plot a display full of text
//        for (currentColumn = 0; currentColumn < 16; currentColumn++) {
//            // Only plot if character is in range
//            if (tempCharacter < strlen(displayString)) {
//                // Display a single column of 8 bits
//                if ((Font3x5[displayString[tempCharacter] - 32][tempColumn] & 0b00000001) != 0) DisplayPlot(x, y, ON);
//                y++;
//                if ((Font3x5[displayString[tempCharacter] - 32][tempColumn] & 0b00000010) != 0) DisplayPlot(x, y, ON);
//                y++;
//                if ((Font3x5[displayString[tempCharacter] - 32][tempColumn] & 0b00000100) != 0) DisplayPlot(x, y, ON);
//                y++;
//                if ((Font3x5[displayString[tempCharacter] - 32][tempColumn] & 0b00001000) != 0) DisplayPlot(x, y, ON);
//                y++;
//                if ((Font3x5[displayString[tempCharacter] - 32][tempColumn] & 0b00010000) != 0) DisplayPlot(x, y, ON);
//
//                // Reset y and add one to x ready for the next column
//                y = 1;
//                x++;
//            }
//            // Increment the column to be displayed
//            tempColumn++;
//
//            // End of character?
//            if (tempColumn == 3) {
//                // Next character
//                tempColumn = 0;
//                tempCharacter++;
//                x++;
//            }
//
//        }
//
//        // Get ready for the next display full
//        column++;
//        if (column == 3) {
//            column = 0;
//            character++;
//        }
//
//        DelayMs(display.scrollDelay);
//    } while(character < strlen(displayString));
//}

void DisplayNumber(unsigned char number){
    unsigned char number1;
    unsigned char number2;
    //char noString[3];

    // Range check
    if (number > 99) number = 99;

    // Displays a number from 00-99 padded with a 0 if required
    if (number < 10) number1 = 0;
    else number1 = number / 10;

    number2 = number - (number1 * 10);

    // Generate a null terminated ASCII string
    displayString[0] = number1 + 48;
    displayString[1] = number2 + 48;
    displayString[2] = '\0';

    DisplayString();
}

//void DisplayTime(void){
//    int tempColumn = 0;
//    int tempCharacter = 0;
//    unsigned char x = 1;
//    unsigned char y = 1;
//    unsigned char currentColumn;
//
//    ClearDisplay();
//
//    // Plot a display full of text
//    for (currentColumn = 0; currentColumn < 16; currentColumn++) {
//        if (tempCharacter == 0 && displayString[0] == '1') {
//            for (y = 1; y < 6; y++) {
//                DisplayPlot(x, y, ON);
//            }
//            y = 1;
//            x++;
//            tempCharacter++;
//        }
//        // Only plot if character is in range
//        if (tempCharacter < strlen(displayString)) {
//            // Display a single column of 8 bits
//            if ((Font3x5[displayString[tempCharacter] - 32][tempColumn] & 0b00000001) != 0) DisplayPlot(x, y, ON);
//            y++;
//            if ((Font3x5[displayString[tempCharacter] - 32][tempColumn] & 0b00000010) != 0) DisplayPlot(x, y, ON);
//            y++;
//            if ((Font3x5[displayString[tempCharacter] - 32][tempColumn] & 0b00000100) != 0) DisplayPlot(x, y, ON);
//            y++;
//            if ((Font3x5[displayString[tempCharacter] - 32][tempColumn] & 0b00001000) != 0) DisplayPlot(x, y, ON);
//            y++;
//            if ((Font3x5[displayString[tempCharacter] - 32][tempColumn] & 0b00010000) != 0) DisplayPlot(x, y, ON);
//
//            // Reset y and add one to x ready for the next column
//            y = 1;
//            x++;
//        }
//
//        // Increment the column to be displayed
//        tempColumn++;
//
//        // End of character?
//        if (tempColumn == 3) {
//            // Next character
//            x++;
//            tempColumn = 0;
//            tempCharacter++;
//
//            if (displayString[tempCharacter] == ':') {
//
//                if (dateTime.sec % 2) {
//                    DisplayPlot(x, 2, ON);
//                    DisplayPlot(x, 4, ON);
//                }
//
//                tempCharacter++;
//                x += 2;
//            }
//        }
//    }
//
//}

void DisplayTime(void){
    int tempColumn = 0;
    int tempCharacter = 0;
    unsigned char x = 0;
    unsigned char y = 0;
    unsigned char currentColumn;

    ClearDisplay();

    // Plot a display full of text
    for (currentColumn = 0; currentColumn < 16; currentColumn++) {
        if (tempCharacter == 0) {
            if (displayString[0] == '1') {
                for (y = 0; y < 5; y++) {
                    DisplayPlot(x, y, ON);
                }
                y = 3;
                x++;
                tempCharacter++;

            } else {
                for (tempColumn = 0; tempColumn < 5; tempColumn++) {
                    if ((Font8x5[displayString[tempCharacter] - 32][tempColumn] & 0b00000001) != 0) DisplayPlot(x, y, ON);
                    y++;
                    if ((Font8x5[displayString[tempCharacter] - 32][tempColumn] & 0b00000010) != 0) DisplayPlot(x, y, ON);
                    y++;
                    if ((Font8x5[displayString[tempCharacter] - 32][tempColumn] & 0b00000100) != 0) DisplayPlot(x, y, ON);
                    y++;
                    if ((Font8x5[displayString[tempCharacter] - 32][tempColumn] & 0b00001000) != 0) DisplayPlot(x, y, ON);
                    y++;
                    if ((Font8x5[displayString[tempCharacter] - 32][tempColumn] & 0b00010000) != 0) DisplayPlot(x, y, ON);
                    y++;
                    if ((Font8x5[displayString[tempCharacter] - 32][tempColumn] & 0b00100000) != 0) DisplayPlot(x, y, ON);
                    y++;
                    if ((Font8x5[displayString[tempCharacter] - 32][tempColumn] & 0b01000000) != 0) DisplayPlot(x, y, ON);
                    y++;
                    if ((Font8x5[displayString[tempCharacter] - 32][tempColumn] & 0b10000000) != 0) DisplayPlot(x, y, ON);

                    y = 0;
                    x++;

                }
                y = 1;
                tempColumn = 0;
                tempCharacter++;
            }
        }


        // Only plot if character is in range
        if (tempCharacter < strlen(displayString)) {
            if (displayString[tempCharacter] == ':') {
                DisplayPlot(x, 2, ON);
                DisplayPlot(x, 4, ON);
                tempCharacter++;
                x += 2;
            }
            // Display a single column of 8 bits
            if ((Font3x5[displayString[tempCharacter] - 32][tempColumn] & 0b00000001) != 0) DisplayPlot(x, y, ON);
            y++;
            if ((Font3x5[displayString[tempCharacter] - 32][tempColumn] & 0b00000010) != 0) DisplayPlot(x, y, ON);
            y++;
            if ((Font3x5[displayString[tempCharacter] - 32][tempColumn] & 0b00000100) != 0) DisplayPlot(x, y, ON);
            y++;
            if ((Font3x5[displayString[tempCharacter] - 32][tempColumn] & 0b00001000) != 0) DisplayPlot(x, y, ON);
            y++;
            if ((Font3x5[displayString[tempCharacter] - 32][tempColumn] & 0b00010000) != 0) DisplayPlot(x, y, ON);

            // Reset y and add one to x ready for the next column
            y = 1;
            x++;
        }

        // Increment the column to be displayed
        tempColumn++;

        // End of character?
        if (tempColumn == 3) {
            // Next character
            x++;
            tempColumn = 0;
            tempCharacter++;
        }
        //        if (displayString[tempCharacter] == ':') {
        //
        //            if (dateTime.sec % 2) {
        //                DisplayPlot(x, 2, ON);
        //                DisplayPlot(x, 4, ON);
        //            }
        //
        //            tempCharacter++;
        //            x += 2;
        //        }

    }

}
